//
//$Id: gridmin_ga.h 441 2010-04-09 17:27:20Z Oleg.Bulychov $
#pragma once

#include "projects/gridmin/gridmin.h"
#include "solvers/ga/ga_common.h"

//__________________________________________________________________________________
//__________________________________________________________________________________
template<>
struct solution<GridMin_Solution, ga_tag>:
    public GridMin_Solution
{
public:
    mutable double wheel_sector_;

    // simple one-point crossover with validation
    template<class E>
    void cross(E* env, uniform_random& rnd, solution<GridMin_Solution, ga_tag>& genome)
    {
        size_t size = grids_set_.size();
        size_t j = rnd.next_SizeT(size);
        for (size_t i = j; i < size; ++i)
        {
            if (grids_set_[i] == genome.grids_set_[i])
                std::swap(grids_set_[i], genome.grids_set_[i]);
            else
                if (grids_set_[i] == 1)
                {
                    genome.grids_set_[i] = 1;
                    genome.inc_Hits(env, i);

                    bool ok = dec_Hits(env,i);
                    if (ok)
                        grids_set_[i] = 0;
                    else
                        inc_Hits(env, i);
                }
                else
                {
                    grids_set_[i] = 1;
                    inc_Hits(env, i);

                    bool ok = genome.dec_Hits(env,i);
                    if (ok)
                        genome.grids_set_[i] = 0;
                    else
                        genome.inc_Hits(env, i);
                }
        }
        changed_ = genome.changed_ = true;
    }

    // mutation a la move in SA
    template<class E>
    void mutate(E* env, uniform_random& rnd, double mutationProbability)
    {
        for (size_t i = 0; i < grids_set_.size(); ++i)
            if (rnd.next_Double() < mutationProbability)
            {
                if (grids_set_[i] == 0)   // add grid
                {
                    grids_set_[i] = 1;
                    inc_Hits(env, i);
                    changed_ = true;
                }
                else                      // remove grid
                {
                    bool ok = dec_Hits(env, i);
                    if (ok)
                    {
                        grids_set_[i] = 0;
                        changed_ = true;
                    }
                    else
                    {
                        inc_Hits(env, i);
                    }
                }
            }
    }

    TCostType get_Fitness() const { return get_Cost(); }
};
//__________________________________________________________________________________

//EOF!
